package com.demo.example;

import lombok.SneakyThrows;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by guishengran on 2017/8/18.
 */
class Task1 implements Runnable {
    private ReentrantLock lock1;
    private ReentrantLock lock2;

    public Task1(ReentrantLock lock1, ReentrantLock lock2) {
        this.lock1 = lock1;
        this.lock2 = lock2;
    }

    @SneakyThrows
    @Override
    public void run() {
        lock1.lock();
//        lock1.tryLock(3, TimeUnit.SECONDS); 防止死锁
        try {
            System.out.println("Task1 get lock1,start sleep...");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock2.lock();
            System.out.println("task1:You can never see me...because we are waiting each other T_T ");
        } finally {
            lock2.unlock();
            lock1.unlock();
        }
    }
}

class Task2 implements Runnable {
    private ReentrantLock lock1;
    private ReentrantLock lock2;

    public Task2(ReentrantLock lock1, ReentrantLock lock2) {
        this.lock1 = lock1;
        this.lock2 = lock2;
    }

    @Override
    public void run() {
        lock2.lock();
        try {
            System.out.println("Task2 get lock2,start sleep...");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock1.lock();
            System.out.println("task2:You can never see me...because we are waiting each other T_T ");
        } finally {
            lock1.unlock();
            lock2.unlock();
        }
    }
}

public class DeadLockTest {
    private static ReentrantLock lock1 = new ReentrantLock();
    private static ReentrantLock lock2 = new ReentrantLock();

    public static void main(String[] args) {
//        DeadLockTest testObj = new DeadLockTest();
        Thread task1 = new Thread(new Task1(lock1, lock2));
        Thread task2 = new Thread(new Task2(lock1, lock2));
        task1.start();
        task2.start();
    }
}